package audio;

import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.MidiUnavailableException;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;

/**
 * 
 * @author Ygor
 *
 */
class MidiPlayer implements MetaEventListener {

	// Midi meta event
	public static final int END_OF_TRACK_MESSAGE = 47;
	private Sequencer sequencer;
	private boolean loop;
	private boolean paused;

	public MidiPlayer() {
		try {
			sequencer = MidiSystem.getSequencer();
			sequencer.open();
			sequencer.addMetaEventListener(this);
		} catch (MidiUnavailableException ex) {
			sequencer = null;
		}
	}

	public void play(Sequence sequence, boolean loop) {
		if (sequencer != null && sequence != null && sequencer.isOpen()) {
			try {
				sequencer.setSequence(sequence);
				sequencer.start();
				this.loop = loop;
			} catch (InvalidMidiDataException ex) {
				ex.printStackTrace();
			}
		}
	}

	@Override
	public void meta(MetaMessage event) {
		if (event.getType() == END_OF_TRACK_MESSAGE) {
			if (sequencer != null && sequencer.isOpen() && loop) {
				sequencer.start();
			}
			else {
				sequencer.stop();
				sequencer.close();
				sequencer = null;
			}
		}
	}

	public void stop() {
		if (null != sequencer && sequencer.isOpen()) {
			sequencer.stop();
			sequencer.setMicrosecondPosition(0);
		}
	}

	public void close() {
		if (null != sequencer && sequencer.isOpen()) {
			sequencer.close();
		}
	}

	public Sequencer getSequencer() {
		return sequencer;
	}

	public void setPaused(boolean paused) {
		if (this.paused != paused && null != sequencer && sequencer.isOpen()) {
			this.paused = paused;
			if (paused) {
				sequencer.stop();
			} else {
				sequencer.start();
			}
		}
	}

	public boolean isPaused() {
		return paused;
	}
}